#include "UdpComm.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDebug>

UdpComm::UdpComm(QObject *parent)
{
    // 读取config.json
    QFile file("config.json");
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "not open file";
        return;
    }


    QJsonObject jsonObj = QJsonDocument::fromJson(file.readAll()).object();

    if(!jsonObj.isEmpty())
    {
        auto udpObj = jsonObj["UDP"].toObject();
        if(!udpObj.isEmpty())
        {
            localIpAddr = udpObj["localIpAddr"].toString();
            localPort = udpObj["localPort"].toInt();
            destIpAddr = udpObj["destIpAddr"].toString();
            destPort = udpObj["destPort"].toInt();

            // 创建socket
            socket = new QUdpSocket();
        }
    }

    file.close();
}

UdpComm::~UdpComm()
{

}

bool UdpComm::initialize()
{
    if(localPort == 0 || !socket)
        return false;
    socket->bind(QHostAddress(localIpAddr), localPort);
    return true;
}

int UdpComm::sendData(const QByteArray &data)
{
    if(!socket || socket->state() != QAbstractSocket::BoundState)
        return 0;
    return socket->writeDatagram(data, QHostAddress(destIpAddr), destPort);
}

int UdpComm::recvData(QByteArray &udpData)
{
    if (socket->hasPendingDatagrams()) {
        // 获取待处理数据报的大小
        qint64 pendingSize = socket->pendingDatagramSize();
        // 调整udpData的大小以匹配待处理数据报的大小
        udpData.resize(pendingSize);
        // 读取数据报
        qint64 bytesRead = socket->readDatagram(udpData.data(), udpData.size());
        if (bytesRead < 0) {
            // 如果读取失败，返回错误码
            qDebug() << "Error reading datagram:" << socket->errorString();
            return -1;
        }

        // 返回实际读取的字节数
        return bytesRead;
    }
    return 0;
}

bool UdpComm::start()
{
    // 重新绑定套接字到指定的地址和端口
    if (socket->state() != QAbstractSocket::BoundState)
    {
        if (!socket->bind(QHostAddress(localIpAddr), localPort)) {
            qDebug() << "Failed to bind socket:" << socket->errorString();
            return false;
        } else {
            qDebug() << "UDP socket restarted and bound to" << localIpAddr << ":" << localPort;
        }
    } else {
        qDebug() << "UDP socket is already active.";
    }
    return true;
}

bool UdpComm::stop()
{
    socket->close();
    qDebug() << "UDP socket closed.";
    return true;
}
